﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Security.Cryptography;
using System.Text;
using System.Data.Entity;


namespace LiveProjectManager.DDD.Services
{
    public class UserService : Base.Service<Domains.User>
    {
        public UserService() : base()
        { 
        }


        override public ICollection<Domains.User> getAll(int paginateBy = 0, int page = 1)
        {
            if (paginateBy > 0)
            {
                if (page <= 0)
                    page = 1;
                return (from u in _repository orderby u.Id select u).Skip(paginateBy * (page - 1)).Take(paginateBy).ToList();
            }
            return (from u in _repository orderby u.Id select u).ToList();
        }


        public ICollection<Domains.User> getAllManagers()
        {
            ICollection<Domains.User> myResults = (
                from u in _repository
                where u.isManager == true
                select u
            ).ToList();
            return (myResults.Count == 0) ? null : myResults;
        }


        override public Domains.User getById(long myId)
        {
            ICollection<Domains.User> myResults = (
                from u in _repository
                where u.Id == myId
                select u
            ).ToList();
            return (myResults.Count != 1) ? null : myResults.First();
        }


        public Domains.User getByEmail(string myEmail)
        {
            ICollection<Domains.User> myResults = (
                from u in _repository
                where u.Email == myEmail
                select u
            ).ToList();
            return (myResults.Count != 1) ? null : myResults.First();
        }


        public Domains.User getByUserName(string myUserName)
        {
            ICollection<Domains.User> myResults = (
                from u in _repository
                where u.UserName == myUserName
                select u
            ).ToList();
            return (myResults.Count != 1) ? null : myResults.First();
        }


        public bool exists(string myUserName)
        {
            return (getByUserName(myUserName) != null);
        }


        public bool create (
            string myUserName, 
            string myEmail, 
            string myClearPassword, 
            bool autoSave = true
		)
		{
			return create (myUserName, myEmail, myClearPassword, "John", "Doe", autoSave);
        }


        public bool create(
            string myUserName, 
            string myEmail, 
            string myClearPassword, 
            string myFirstName, 
            string myLastName, 
            bool autoSave = true
        )
        {
            try {
                // User already exists.
                if (exists(myUserName))
                    return false;

                // Create the new user.
                Domains.User myNewUser = new Domains.User() { 
                    UserName = myUserName, 
                    Email = myEmail, 
                    Password = encryptPassword(myClearPassword),
                    FirstName = myFirstName,
                    LastName = myLastName,
                    isManager = false,
                    CreatedOn = DateTime.Now
                };

                // Insert in repository.
                _repository.Add(myNewUser);
                if (autoSave)
                    _context.SaveChanges();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }


        override public bool remove(long myUserId, bool autoSave = true)
        {
            Domains.User myUser = getById(myUserId);
            if (myUser == null)
                return false;
            _repository.Remove(myUser);
            if (autoSave)
                _context.SaveChanges();
            return true;
        }


        public static bool isPasswordValid(Domains.User myUser, string myClearPassword)
        {
            return (myUser.Password == encryptPassword(myClearPassword));
        }


        private static string byteArrayToString(byte[] myInputArray)
        {
            StringBuilder output = new StringBuilder("");
            for (int i = 0; i < myInputArray.Length; i++)
                output.Append(myInputArray[i].ToString("X2"));
            return output.ToString();
        }


        public static string encryptPassword(string myClearPassword)
        {
            UTF8Encoding myEncoder = new UTF8Encoding();
            SHA512Managed myHasher = new SHA512Managed();
            return byteArrayToString(
                myHasher.ComputeHash(myEncoder.GetBytes(myClearPassword))
            );
        }
    }
}